# dev.setupMiddlewares

- **类型：**

```ts
type SetupMiddlewaresContext = {
  sockWrite: (
    type: string,
    data?: string | boolean | Record<string, any>,
  ) => void;
  environments: EnvironmentAPI;
};

type SetupMiddlewaresFn = (
  middlewares: {
    unshift: (...handlers: RequestHandler[]) => void;
    push: (...handlers: RequestHandler[]) => void;
  },
  context: SetupMiddlewaresContext,
) => void;

type SetupMiddlewares = SetupMiddlewaresFn | SetupMiddlewaresFn[];
```

- **默认值：** `undefined`
- **版本：** `>= 1.4.0`

用于在开发服务器中添加自定义的中间件。

> 查看 [开发服务器 - 中间件](/guide/basic/server#中间件) 了解更多。

## 基本用法

`setupMiddlewares` 函数接收一个 `middlewares` 数组，你可以通过 `unshift` 和 `push` 方法来添加自定义的中间件：

- 使用 `unshift` 在数组开头添加中间件，早于内置中间件执行。
- 使用 `push` 在数组末尾添加中间件，晚于内置中间件执行。

```ts title="rsbuild.config.ts"
export default {
  dev: {
    setupMiddlewares: (middlewares) => {
      middlewares.unshift((req, res, next) => {
        console.log('first');
        next();
      });

      middlewares.push((req, res, next) => {
        console.log('last');
        next();
      });
    },
  },
};
```

中间件可以是一个异步函数：

```ts title="rsbuild.config.ts"
export default {
  dev: {
    setupMiddlewares: (middlewares) => {
      middlewares.unshift(async (req, res, next) => {
        await someAsyncOperation();
        next();
      });
    },
  },
};
```

`setupMiddlewares` 也支持传入一个数组，数组中的每一项都是一个用于配置中间件的函数：

```ts title="rsbuild.config.ts"
export default {
  dev: {
    setupMiddlewares: [
      (middlewares) => {
        // ...
      },
      (middlewares) => {
        // ...
      },
    ],
  },
};
```

:::tip
在 Rsbuild 1.4.0 之前的版本中，`setupMiddlewares` 必须传入一个数组。
:::

## Context 对象

`setupMiddlewares` 函数的第二个参数是 `context` 对象，该对象提供了一些服务器上下文和 API。

### environments

提供 Rsbuild 的 [environment API](/api/javascript-api/environment-api#environment-api)，详见 [Dev server API - environments](/api/javascript-api/dev-server-api#environments)。

```ts title="rsbuild.config.ts"
export default {
  dev: {
    setupMiddlewares: (middlewares, { environments }) => {
      middlewares.unshift(async (req, _res, next) => {
        const webStats = await environments.web.getStats();
        console.log(webStats.toJson({ all: false }));
        next();
      });
    },
  },
};
```

### sockWrite

向 HMR 客户端传递一些消息，详见 [Dev server API - sockWrite](/api/javascript-api/dev-server-api#sockwrite)。

例如，如果你发送一个 `'static-changed'` 的消息，页面将会重新加载。

```ts title="rsbuild.config.ts"
export default {
  dev: {
    setupMiddlewares: (middlewares, { sockWrite }) => {
      if (someCondition) {
        sockWrite('static-changed');
      }
    },
  },
};
```
